home *** CD-ROM | disk | FTP | other *** search
/ Giga Games 1 / Giga Games.iso / net / hack / 3_1_3 / sys / amiga / winami.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-07-08  |  31.7 KB  |  1,425 lines

  1. /*    SCCS Id: @(#)winami.c    3.1    93/04/02 */
  2. /* Copyright (c) Gregg Wonderly, Naperville, Illinois,  1991,1992,1993. */
  3. /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5. #include "amiga:windefs.h"
  6. #include "amiga:winext.h"
  7. #include "amiga:winproto.h"
  8.  
  9. #ifdef AMIGA_INTUITION
  10.  
  11. #ifdef    SHAREDLIB
  12. struct DosLibrary *DOSBase;
  13. #else
  14. struct amii_DisplayDesc *amiIDisplay;    /* the Amiga Intuition descriptor */
  15. #endif
  16.  
  17. int clipping = 0;
  18. int clipx=0;
  19. int clipy=0;
  20. int clipxmax=0;
  21. int clipymax=0;
  22. int scrollmsg = 1;
  23. int alwaysinvent = 0;
  24.  
  25. #ifndef    SHAREDLIB
  26.  
  27. /* Interface definition, for use by windows.c and winprocs.h to provide
  28.  * the intuition interface for the amiga...
  29.  */
  30. struct window_procs amii_procs =
  31. {
  32.     "amii",
  33.     amii_init_nhwindows,
  34.     amii_player_selection,
  35.     amii_askname,
  36.     amii_get_nh_event,
  37.     amii_exit_nhwindows,
  38.     amii_suspend_nhwindows,
  39.     amii_resume_nhwindows,
  40.     amii_create_nhwindow,
  41.     amii_clear_nhwindow,
  42.     amii_display_nhwindow,
  43.     amii_destroy_nhwindow,
  44.     amii_curs,
  45.     amii_putstr,
  46.     amii_display_file,
  47.     amii_start_menu,
  48.     amii_add_menu,
  49.     amii_end_menu,
  50.     amii_select_menu,
  51.     amii_update_inventory,
  52.     amii_mark_synch,
  53.     amii_wait_synch,
  54. #ifdef CLIPPING
  55.     amii_cliparound,
  56. #endif
  57.     amii_print_glyph,
  58.     amii_raw_print,
  59.     amii_raw_print_bold,
  60.     amii_nhgetch,
  61.     amii_nh_poskey,
  62.     amii_bell,
  63.     amii_doprev_message,
  64.     amii_yn_function,
  65.     amii_getlin,
  66. #ifdef COM_COMPL
  67.     amii_get_ext_cmd,
  68. #endif /* COM_COMPL */
  69.     amii_number_pad,
  70.     amii_delay_output,
  71. #ifdef CHANGE_COLOR    /* only a Mac option currently */
  72.     amii_change_color,
  73.     amii_get_color_string,
  74. #endif
  75.     /* other defs that really should go away (they're tty specific) */
  76.     amii_delay_output,
  77.     amii_delay_output,
  78.     amii_outrip,
  79. };
  80.  
  81. /* The view window layout uses the same function names so we can use
  82.  * a shared library to allow the executable to be smaller.
  83.  */
  84. struct window_procs amiv_procs =
  85. {
  86.     "amiv",
  87.     amii_init_nhwindows,
  88.     amii_player_selection,
  89.     amii_askname,
  90.     amii_get_nh_event,
  91.     amii_exit_nhwindows,
  92.     amii_suspend_nhwindows,
  93.     amii_resume_nhwindows,
  94.     amii_create_nhwindow,
  95.     amii_clear_nhwindow,
  96.     amii_display_nhwindow,
  97.     amii_destroy_nhwindow,
  98.     amii_curs,
  99.     amii_putstr,
  100.     amii_display_file,
  101.     amii_start_menu,
  102.     amii_add_menu,
  103.     amii_end_menu,
  104.     amii_select_menu,
  105.     amii_update_inventory,
  106.     amii_mark_synch,
  107.     amii_wait_synch,
  108. #ifdef CLIPPING
  109.     amii_cliparound,
  110. #endif
  111.     amii_print_glyph,
  112.     amii_raw_print,
  113.     amii_raw_print_bold,
  114.     amii_nhgetch,
  115.     amii_nh_poskey,
  116.     amii_bell,
  117.     amii_doprev_message,
  118.     amii_yn_function,
  119.     amii_getlin,
  120. #ifdef COM_COMPL
  121.     amii_get_ext_cmd,
  122. #endif /* COM_COMPL */
  123.     amii_number_pad,
  124.     amii_delay_output,
  125. #ifdef CHANGE_COLOR    /* only a Mac option currently */
  126.     amii_change_color,
  127.     amii_get_color_string,
  128. #endif
  129.     /* other defs that really should go away (they're tty specific) */
  130.     amii_delay_output,
  131.     amii_delay_output,
  132.     amii_outrip,
  133. };
  134. #endif
  135.  
  136. #ifndef    SHAREDLIB
  137. unsigned short amii_initmap[ 1L << DEPTH ] =
  138. {
  139.     0x0000, /* color #0 */
  140.     0x0FFF, /* color #1 */
  141.     0x0830, /* color #2 */
  142.     0x07ac, /* color #3 */
  143.     0x0181, /* color #4 */
  144.     0x0C06, /* color #5 */
  145.     0x023E, /* color #6 */
  146.     0x0c00  /* color #7 */
  147. #ifdef    VIEWWINDOW
  148.     0x0AAA,
  149.     0x0fff,
  150.     0x0444,
  151.     0x0666,
  152.     0x0888,
  153.     0x0bbb,
  154.     0x0ddd,
  155.     0x0222,
  156. #endif
  157. };
  158. #endif
  159.  
  160. struct Rectangle lastinvent, lastmsg;
  161.  
  162. static int FDECL( put_ext_cmd, ( char *, int, struct amii_WinDesc *, int ) );
  163.  
  164. #ifdef    SHAREDLIB
  165. WinamiBASE *WinamiBase;
  166.  
  167. int
  168. __UserLibInit( void )
  169. {
  170.     WinamiBase = (WinamiBASE *)getreg( REG_A6 );
  171.     if ( (DOSBase = (struct DosLibrary *)
  172.         OpenLibrary("dos.library", 0)) == NULL)
  173.     {
  174.     Abort(AG_OpenLib | AO_DOSLib);
  175.     }
  176.  
  177.     if ( (IntuitionBase = (struct IntuitionBase *)
  178.         OpenLibrary("intuition.library", INTUITION_VERSION)) == NULL)
  179.     {
  180.     Abort(AG_OpenLib | AO_Intuition);
  181.     }
  182.  
  183.     if ( (GfxBase = (struct GfxBase *)
  184.         OpenLibrary("graphics.library", GRAPHICS_VERSION)) == NULL)
  185.     {
  186.     Abort(AG_OpenLib | AO_GraphicsLib);
  187.     }
  188.  
  189. #ifdef    VIEWWINDOW
  190.     if ( (LayersBase = (struct Library *)
  191.         OpenLibrary("layers.library", 0)) == NULL)
  192.     {
  193.     Abort(AG_OpenLib | AO_LayersLib);
  194.     }
  195. #endif
  196.  
  197.     return( 0 );
  198. }
  199.  
  200. void
  201. __UserLibCleanup( void )
  202. {
  203.     amii_cleanup();
  204. }
  205.  
  206. char _ProgramName[ 100 ] = "Nethack";
  207. long __curdir;
  208. long _WBenchMsg;
  209. int _OSERR;
  210. #endif
  211.  
  212. #ifndef TTY_GRAPHICS    /* this should be shared better */
  213. char morc;  /* the character typed in response to a --more-- prompt */
  214. #endif
  215. char spaces[ 76 ] =
  216. "                                                                           ";
  217.  
  218. #ifndef    SHAREDLIB
  219. winid WIN_BASE = WIN_ERR;
  220. winid amii_rawprwin = WIN_ERR;
  221. #endif
  222.  
  223. #ifdef    VIEWWINDOW
  224. winid WIN_VIEW = WIN_ERR;
  225. winid WIN_VIEWBOX = WIN_ERR;
  226. #endif
  227.  
  228. /* Changed later during window/screen opens... */
  229. int txwidth = FONTWIDTH, txheight = FONTHEIGHT, txbaseline = FONTBASELINE;
  230.  
  231. /* If a 240 or more row screen is in front when we start, this will be
  232.  * set to 1, and the windows will be given borders to allow them to be
  233.  * arranged differently.  The Message window may eventually get a scroller...
  234.  */
  235. #ifndef    SHAREDLIB
  236. int bigscreen = 0;
  237. #endif
  238. #ifdef    VIEWWINDOW
  239. struct BitMap amii_vbm;
  240. #endif
  241.  
  242. /* This gadget data is replicated for menu/text windows... */
  243. struct PropInfo PropScroll = { AUTOKNOB|FREEVERT,
  244.                     0xffff,0xffff, 0xffff,0xffff, };
  245. struct Image Image1 = { 0,0, 7,102, 0, NULL, 0x0000,0x0000, NULL };
  246. struct Gadget MenuScroll = {
  247.     NULL, -15,10, 15,-19, GRELRIGHT|GRELHEIGHT,
  248.     RELVERIFY|FOLLOWMOUSE|RIGHTBORDER|GADGIMMEDIATE|RELVERIFY,
  249.     PROPGADGET, (APTR)&Image1, NULL, NULL, NULL, (APTR)&PropScroll,
  250.     1, NULL
  251. };
  252.  
  253. /* This gadget is for the message window... */
  254. struct PropInfo MsgPropScroll = { AUTOKNOB|FREEVERT,
  255.                     0xffff,0xffff, 0xffff,0xffff, };
  256. struct Image MsgImage1 = { 0,0, 7,102, 0, NULL, 0x0000,0x0000, NULL };
  257. struct Gadget MsgScroll = {
  258.     NULL, -14,10, 13,-19, GRELRIGHT|GRELHEIGHT,
  259.     RELVERIFY|FOLLOWMOUSE|RIGHTBORDER|GADGIMMEDIATE|RELVERIFY,
  260.     PROPGADGET, (APTR)&MsgImage1, NULL, NULL, NULL, (APTR)&MsgPropScroll,
  261.     1, NULL
  262. };
  263.  
  264. int wincnt=0;   /* # of nh windows opened */
  265.  
  266. /* We advertise a public screen to allow some people to do other things
  267.  * while they are playing...  like compiling...
  268.  */
  269.  
  270. #ifdef  INTUI_NEW_LOOK
  271. struct TagItem tags[] =
  272. {
  273.     { WA_PubScreenName, (ULONG)"NetHack", },
  274.     { TAG_DONE, 0, },
  275. };
  276. #endif
  277.  
  278. /*
  279.  * The default dimensions and status values for each window type.  The
  280.  * data here is generally changed in create_nhwindow(), so beware that
  281.  * what you see here may not be exactly what you get.
  282.  */
  283. struct win_setup new_wins[] =
  284. {
  285.  
  286.     /* First entry not used, types are based at 1 */
  287.     {{0}},
  288.  
  289.     /* NHW_MESSAGE */
  290.     {{0,1,640,11,0xff,0xff,
  291.     NEWSIZE|GADGETUP|GADGETDOWN|MOUSEMOVE|MOUSEBUTTONS|RAWKEY,
  292.     BORDERLESS|ACTIVATE|SMART_REFRESH
  293. #ifdef  INTUI_NEW_LOOK
  294.     |WFLG_NW_EXTENDED
  295. #endif
  296.     ,
  297.     NULL,NULL,(UBYTE*)"Messages",NULL,NULL,640,40,0xffff,0xffff,CUSTOMSCREEN,
  298. #ifdef  INTUI_NEW_LOOK
  299.     tags,
  300. #endif
  301.     },
  302.     0,0,1,1,80,80},
  303.  
  304.     /* NHW_STATUS */
  305.     {{0,181,640,24,0xff,0xff, RAWKEY|MENUPICK|DISKINSERTED,
  306.     BORDERLESS|ACTIVATE|SMART_REFRESH
  307. #ifdef  INTUI_NEW_LOOK
  308.     |WFLG_NW_EXTENDED
  309. #endif
  310.     ,
  311.     NULL,NULL,(UBYTE*)"Game Status",NULL,NULL,-1,-1,0xffff,0xffff,CUSTOMSCREEN,
  312. #ifdef  INTUI_NEW_LOOK
  313.     tags,
  314. #endif
  315.     },
  316.     0,0,2,2,78,78},
  317.  
  318.     /* NHW_MAP */
  319.     {{0,0,WIDTH,WINDOWHEIGHT,0xff,0xff,
  320.     RAWKEY|MENUPICK|MOUSEBUTTONS|ACTIVEWINDOW|MOUSEMOVE,
  321.     BORDERLESS|ACTIVATE|SMART_REFRESH|BACKDROP
  322. #ifdef  INTUI_NEW_LOOK
  323.     |WFLG_NW_EXTENDED
  324. #endif
  325.     ,
  326.     NULL,NULL,(UBYTE*)"Dungeon Map",NULL,NULL,-1,-1,0xffff,0xffff,CUSTOMSCREEN,
  327. #ifdef  INTUI_NEW_LOOK
  328.     tags,
  329. #endif
  330.     },
  331.     0,0,22,22,80,80},
  332.  
  333.     /* NHW_MENU */
  334.     {{400,10,10,10,80,30,
  335.     RAWKEY|MENUPICK|DISKINSERTED|MOUSEMOVE|MOUSEBUTTONS|
  336.     GADGETUP|GADGETDOWN|CLOSEWINDOW|VANILLAKEY|NEWSIZE|INACTIVEWINDOW,
  337.     WINDOWSIZING|WINDOWCLOSE|WINDOWDRAG|ACTIVATE|SMART_REFRESH
  338. #ifdef  INTUI_NEW_LOOK
  339.     |WFLG_NW_EXTENDED
  340. #endif
  341.     ,
  342.     &MenuScroll,NULL,(UBYTE*)"Pick an Item",
  343.     NULL,NULL,-1,-1,0xffff,0xffff,CUSTOMSCREEN,
  344. #ifdef  INTUI_NEW_LOOK
  345.     tags,
  346. #endif
  347.     },
  348.     0,0,1,1,22,78},
  349.  
  350.     /* NHW_TEXT */
  351.     {{0,0,640,200,0xff,0xff,
  352.     RAWKEY|MENUPICK|DISKINSERTED|MOUSEMOVE|
  353.     GADGETUP|CLOSEWINDOW|VANILLAKEY|NEWSIZE,
  354.     WINDOWSIZING|WINDOWCLOSE|WINDOWDRAG|ACTIVATE|SMART_REFRESH
  355. #ifdef  INTUI_NEW_LOOK
  356.     |WFLG_NW_EXTENDED
  357. #endif
  358.     ,
  359.     &MenuScroll,NULL,(UBYTE*)NULL,NULL,NULL,-1,-1,0xffff,0xffff,CUSTOMSCREEN,
  360. #ifdef  INTUI_NEW_LOOK
  361.     tags,
  362. #endif
  363.     },
  364.     0,0,1,1,22,78},
  365.  
  366.     /* NHW_BASE */
  367.     {{0,0,WIDTH,WINDOWHEIGHT,0xff,0xff,
  368.     RAWKEY|MENUPICK|MOUSEBUTTONS,
  369.     BORDERLESS|ACTIVATE|SMART_REFRESH|BACKDROP
  370. #ifdef  INTUI_NEW_LOOK
  371.     |WFLG_NW_EXTENDED
  372. #endif
  373.     ,
  374.     NULL,NULL,(UBYTE*)NULL,NULL,NULL,-1,-1,0xffff,0xffff,CUSTOMSCREEN,
  375. #ifdef  INTUI_NEW_LOOK
  376.     tags,
  377. #endif
  378.     },
  379.     0,0,22,22,80,80},
  380.  
  381. #ifdef    VIEWWINDOW
  382.     /* NHW_VIEW */
  383.     {{0,0,WIDTH,WINDOWHEIGHT,0xff,0xff,
  384.     RAWKEY|MENUPICK|MOUSEBUTTONS,
  385.     BORDERLESS|ACTIVATE|SMART_REFRESH
  386. #ifdef  INTUI_NEW_LOOK
  387.     |WFLG_NW_EXTENDED
  388. #endif
  389.     ,
  390.     NULL,NULL,(UBYTE*)NULL,NULL,NULL,-1,-1,0xffff,0xffff,CUSTOMSCREEN,
  391. #ifdef  INTUI_NEW_LOOK
  392.     tags,
  393. #endif
  394.     },
  395.     0,0,VIEWCHARWIDTH,VIEWCHARHEIGHT,VIEWCHARWIDTH,VIEWCHARHEIGHT},
  396.  
  397.     /* NHW_VIEWBOX */
  398.     {{0,0,WIDTH,WINDOWHEIGHT,0xff,0xff,
  399.     RAWKEY|MENUPICK|MOUSEBUTTONS|REFRESHWINDOW,
  400.     WINDOWSIZING|WINDOWDRAG|ACTIVATE|SIMPLE_REFRESH
  401. #ifdef  INTUI_NEW_LOOK
  402.     |WFLG_NW_EXTENDED
  403. #endif
  404.     ,
  405.     NULL,NULL,(UBYTE*)NULL,NULL,NULL,-1,-1,0xffff,0xffff,CUSTOMSCREEN,
  406. #ifdef  INTUI_NEW_LOOK
  407.     tags,
  408. #endif
  409.     },
  410.     0,0,VIEWCHARWIDTH,VIEWCHARHEIGHT,VIEWCHARWIDTH,VIEWCHARHEIGHT},
  411. #endif
  412. };
  413.  
  414. const char winpanicstr[] = "Bad winid %d in %s()";
  415.  
  416. /* The opened windows information */
  417. struct amii_WinDesc *amii_wins[ MAXWIN + 1 ];
  418.  
  419. #ifdef  INTUI_NEW_LOOK
  420. UWORD scrnpens[] =
  421. {
  422. #ifndef    VIEWWINDOW
  423.     C_BLACK,        /* DETAILPEN        */
  424.     C_BLUE,         /* BLOCKPEN         */
  425.     C_BROWN,        /* TEXTPEN          */
  426.     C_WHITE,        /* SHINEPEN         */
  427.     C_BLUE,        /* SHADOWPEN        */
  428.     C_CYAN,        /* FILLPEN          */
  429.     C_WHITE,        /* FILLTEXTPEN      */
  430.     C_CYAN,        /* BACKGROUNDPEN    */
  431.     C_RED,        /* HIGHLIGHTTEXTPEN */
  432. #else
  433.     C_BLACK,        /* DETAILPEN        */
  434.     C_BLUE,        /* BLOCKPEN         */
  435.     C_BROWN,        /* TEXTPEN          */
  436.     C_WHITE,        /* SHINEPEN         */
  437.     C_BLUE,        /* SHADOWPEN        */
  438.     C_CYAN,        /* FILLPEN          */
  439.     C_WHITE,        /* FILLTEXTPEN      */
  440.     C_CYAN,        /* BACKGROUNDPEN    */
  441.     C_RED,        /* HIGHLIGHTTEXTPEN */
  442. #endif
  443. };
  444.  
  445. struct TagItem scrntags[] =
  446. {
  447.     { SA_PubName, (ULONG)"NetHack" },
  448.     { SA_Overscan, OSCAN_TEXT },
  449.     { SA_Pens, (ULONG)scrnpens },
  450.     { SA_DisplayID, 0 },
  451.     { TAG_DONE, 0 },
  452. };
  453. #endif
  454.  
  455. struct NewScreen NewHackScreen =
  456. {
  457.     0, 0, WIDTH, SCREENHEIGHT, DEPTH,
  458.     C_BROWN, C_BLUE,     /* DetailPen, BlockPen */
  459.     HIRES,
  460.     CUSTOMSCREEN
  461. #ifdef  INTUI_NEW_LOOK
  462.     |NS_EXTENDED
  463. #endif
  464.     ,
  465.     &Hack80,  /* Font */
  466.     NULL,     /*(UBYTE *)" NetHack X.Y.Z" */
  467.     NULL,     /* Gadgets */
  468.     NULL,     /* CustomBitmap */
  469. #ifdef  INTUI_NEW_LOOK
  470.     scrntags,
  471. #endif
  472. };
  473.  
  474. /*
  475.  * plname is filled either by an option (-u Player  or  -uPlayer) or
  476.  * explicitly (by being the wizard) or by askname.
  477.  * It may still contain a suffix denoting pl_character.
  478.  * Always called after init_nhwindows() and before display_gamewindows().
  479.  */
  480. void
  481. amii_askname()
  482. {
  483.     *plname = 0;
  484.     do {
  485.     getlin( "Who are you?", plname );
  486.     } while( strlen( plname ) == 0 );
  487.  
  488.     if( *plname == '\33' )
  489.     {
  490.     clearlocks();
  491.     exit_nhwindows(NULL);
  492.     terminate(0);
  493.     }
  494. }
  495.  
  496. #include "Amiga:char.c"
  497.  
  498. /* Get the player selection character */
  499.  
  500. void
  501. amii_player_selection()
  502. {
  503.     register struct Window *cwin;
  504.     register struct IntuiMessage *imsg;
  505.     register int aredone = 0;
  506.     register struct Gadget *gd;
  507.     static int once=0;
  508.     long class, code;
  509.  
  510.     amii_clear_nhwindow( WIN_BASE );
  511.     if( *pl_character ){
  512.     pl_character[ 0 ] = toupper( pl_character[ 0 ] );
  513.     if( index( pl_classes, pl_character[ 0 ] ) )
  514.         return;
  515.     }
  516.  
  517.     if( !once ){
  518.     if( bigscreen ){
  519.         Type_NewWindowStructure1.TopEdge =
  520.           (HackScreen->Height/2) - (Type_NewWindowStructure1.Height/2);
  521.     }
  522.     for( gd = Type_NewWindowStructure1.FirstGadget; gd;
  523.       gd = gd->NextGadget )
  524.     {
  525.         if( gd->GadgetID != 0 )
  526.         SetBorder( gd );
  527.     }
  528.     once = 1;
  529.     }
  530.  
  531.     Type_NewWindowStructure1.Screen = HackScreen;
  532.     if( ( cwin = OpenShWindow( (void *)&Type_NewWindowStructure1 ) ) == NULL )
  533.     {
  534.     return;
  535.     }
  536.     WindowToFront( cwin );
  537.  
  538.     while( !aredone )
  539.     {
  540.     WaitPort( cwin->UserPort );
  541.     while( ( imsg = (void *) GetMsg( cwin->UserPort ) ) != NULL )
  542.     {
  543.         class = imsg->Class;
  544.         code = imsg->Code;
  545.         gd = (struct Gadget *)imsg->IAddress;
  546.         ReplyMsg( (struct Message *)imsg );
  547.  
  548.         switch( class )
  549.         {
  550.         case VANILLAKEY:
  551.         if( index( pl_classes, toupper( code ) ) )
  552.         {
  553.             pl_character[0] = toupper( code );
  554.             aredone = 1;
  555.         }
  556.         else if( code == ' ' || code == '\n' || code == '\r' )
  557.         {
  558. #ifdef  TOURIST
  559.             strcpy( pl_character, roles[ rnd( 11 ) ] );
  560. #else
  561.             strcpy( pl_character, roles[ rnd( 10 ) ] );
  562. #endif
  563.             aredone = 1;
  564.             amii_clear_nhwindow( WIN_BASE );
  565.             CloseShWindow( cwin );
  566.             RandomWindow( pl_character );
  567.             return;
  568.         }
  569.         else if( code == 'q' || code == 'Q' )
  570.         {
  571.         CloseShWindow( cwin );
  572.         clearlocks();
  573.         exit_nhwindows(NULL);
  574.         terminate(0);
  575.         }
  576.         else
  577.             DisplayBeep( NULL );
  578.         break;
  579.  
  580.         case GADGETUP:
  581.         switch( gd->GadgetID )
  582.         {
  583.         case 1: /* Random Character */
  584. #ifdef  TOURIST
  585.             strcpy( pl_character, roles[ rnd( 11 ) ] );
  586. #else
  587.             strcpy( pl_character, roles[ rnd( 10 ) ] );
  588. #endif
  589.             amii_clear_nhwindow( WIN_BASE );
  590.             CloseShWindow( cwin );
  591.             RandomWindow( pl_character );
  592.             return;
  593.  
  594.         default:
  595.             pl_character[0] = gd->GadgetID;
  596.             break;
  597.         }
  598.         aredone = 1;
  599.         break;
  600.  
  601.         case CLOSEWINDOW:
  602.         CloseShWindow( cwin );
  603.         clearlocks();
  604.         exit_nhwindows(NULL);
  605.         terminate(0);
  606.         break;
  607.         }
  608.     }
  609.     }
  610.     amii_clear_nhwindow( WIN_BASE );
  611.     CloseShWindow( cwin );
  612. }
  613.  
  614. #include "Amiga:randwin.c"
  615.  
  616. void
  617. RandomWindow( name )
  618.     char *name;
  619. {
  620.     struct MsgPort *tport;
  621.     struct timerequest *trq;
  622.     static int once = 0;
  623.     struct Gadget *gd;
  624.     struct Window *w;
  625.     struct IntuiMessage *imsg;
  626.     int ticks = 0, aredone = 0, timerdone = 0;
  627.     long mask, got;
  628.  
  629.     tport = CreatePort( 0, 0 );
  630.     trq = (struct timerequest *)CreateExtIO( tport, sizeof( *trq ) );
  631.     if( tport == NULL || trq == NULL )
  632.     {
  633. allocerr:
  634.     if( tport ) DeletePort( tport );
  635.     if( trq ) DeleteExtIO( (struct IORequest *)trq );
  636.     Delay( 8 * 50 );
  637.     return;
  638.     }
  639.  
  640.     if( OpenDevice( TIMERNAME, UNIT_VBLANK, (struct IORequest *)trq, 0L ) != 0 )
  641.     goto allocerr;
  642.  
  643.     trq->tr_node.io_Command = TR_ADDREQUEST;
  644.     trq->tr_time.tv_secs = 8;
  645.     trq->tr_time.tv_micro = 0;
  646.  
  647.     SendIO( (struct IORequest *)trq );
  648.  
  649.     /* Place the name in the center of the screen */
  650.     Rnd_IText5.IText = name;
  651.     Rnd_IText6.LeftEdge = Rnd_IText4.LeftEdge +
  652.         (strlen(Rnd_IText4.IText)+1)*8;
  653.     Rnd_NewWindowStructure1.Width = (
  654.         (strlen( Rnd_IText2.IText )+1) * 8 ) +
  655.         HackScreen->WBorLeft + HackScreen->WBorRight;
  656.     Rnd_IText5.LeftEdge = (Rnd_NewWindowStructure1.Width -
  657.         (strlen(name)*8))/2;
  658.  
  659.     gd = Rnd_NewWindowStructure1.FirstGadget;
  660.     gd->LeftEdge = (Rnd_NewWindowStructure1.Width - gd->Width)/2;
  661.     /* Chose correct modifier */
  662.     Rnd_IText6.IText = "a";
  663.     switch( *name )
  664.     {
  665.     case 'a': case 'e': case 'i': case 'o':
  666.     case 'u': case 'A': case 'E': case 'I':
  667.     case 'O': case 'U':
  668.     Rnd_IText6.IText = "an";
  669.     break;
  670.     }
  671.  
  672.     if( !once )
  673.     {
  674.     if( bigscreen )
  675.     {
  676.         Rnd_NewWindowStructure1.TopEdge =
  677.         (HackScreen->Height/2) - (Rnd_NewWindowStructure1.Height/2);
  678.     }
  679.     for( gd = Rnd_NewWindowStructure1.FirstGadget; gd; gd = gd->NextGadget )
  680.     {
  681.         if( gd->GadgetID != 0 )
  682.         SetBorder( gd );
  683.     }
  684.     Rnd_NewWindowStructure1.IDCMPFlags |= VANILLAKEY;
  685.  
  686.     once = 1;
  687.     }
  688.  
  689.     Rnd_NewWindowStructure1.Screen = HackScreen;
  690.     if( ( w = OpenShWindow( (void *)&Rnd_NewWindowStructure1 ) ) == NULL )
  691.     {
  692.     AbortIO( (struct IORequest *)trq );
  693.     WaitIO( (struct IORequest *)trq );
  694.     CloseDevice( (struct IORequest *)trq );
  695.     DeleteExtIO( (struct IORequest *) trq );
  696.     DeletePort( tport );
  697.     Delay( 50 * 8 );
  698.     return;
  699.     }
  700.  
  701.     PrintIText( w->RPort, &Rnd_IntuiTextList1, 0, 0 );
  702.  
  703.     mask = (1L << tport->mp_SigBit)|(1L << w->UserPort->mp_SigBit);
  704.     while( !aredone )
  705.     {
  706.     got = Wait( mask );
  707.     if( got & (1L << tport->mp_SigBit ) )
  708.     {
  709.         aredone = 1;
  710.         timerdone = 1;
  711.         GetMsg( tport );
  712.         }
  713.         while( w && ( imsg = (struct IntuiMessage *) GetMsg( w->UserPort ) ) )
  714.         {
  715.         switch( imsg->Class )
  716.         {
  717.         /* Must be up for a little while... */
  718.         case INACTIVEWINDOW:
  719.         if( ticks >= 40 )
  720.             aredone = 1;
  721.         break;
  722.  
  723.         case INTUITICKS:
  724.         ++ticks;
  725.         break;
  726.  
  727.         case GADGETUP:
  728.         aredone = 1;
  729.         break;
  730.  
  731.         case VANILLAKEY:
  732.         if(imsg->Code=='\n' || imsg->Code==' ' || imsg->Code=='\r')
  733.             aredone = 1;
  734.         break;
  735.         }
  736.         ReplyMsg( (struct Message *)imsg );
  737.         }
  738.     }
  739.  
  740.     if( !timerdone )
  741.     {
  742.     AbortIO( (struct IORequest *)trq );
  743.     WaitIO( (struct IORequest *)trq );
  744.     }
  745.  
  746.     CloseDevice( (struct IORequest *)trq );
  747.     DeleteExtIO( (struct IORequest *) trq );
  748.     DeletePort( tport );
  749.     if(w) CloseShWindow( w );
  750. }
  751.  
  752. /* this should probably not be needed (or be renamed)
  753. void
  754. flush_output(){} */
  755.  
  756. #ifdef COM_COMPL
  757. /* Read in an extended command - doing command line completion for
  758.  * when enough characters have been entered to make a unique command.
  759.  */
  760. void
  761. amii_get_ext_cmd(bufp)
  762. register char *bufp;
  763. {
  764.     register char *obufp = bufp;
  765.     register int c;
  766.     int com_index, oindex;
  767.     struct amii_WinDesc *cw;
  768.     struct Window *w;
  769.     int colx;
  770.     int did_comp=0;    /* did successful completion? */
  771.     int bottom = 0;
  772.  
  773.     if( WIN_MESSAGE == WIN_ERR || ( cw = amii_wins[ WIN_MESSAGE ] ) == NULL )
  774.     panic(winpanicstr, WIN_MESSAGE, "get_ext_cmd");
  775.     amii_clear_nhwindow( NHW_MESSAGE );
  776.     if( scrollmsg )
  777.     {
  778.     pline("#");
  779.     amii_putstr( WIN_MESSAGE, -1, " " );
  780.     }
  781.     else
  782.     {
  783.     pline("# ");
  784.     }
  785.     colx = 3;
  786.     w = cw->win;
  787.  
  788.     if( bigscreen )
  789.     {
  790.         bottom = amii_msgborder( w );
  791.     }
  792.  
  793.     while((c = WindowGetchar()) != EOF)
  794.     {
  795.     amii_curs( WIN_MESSAGE, colx, bottom );
  796.     if(c == '?' )
  797.     {
  798.         int win, i, sel;
  799.         char buf[ 100 ];
  800.  
  801.         if(did_comp){
  802.         while(bufp!=obufp){
  803.             bufp--;
  804.             amii_curs(WIN_MESSAGE, --colx, bottom);
  805.             Text(w->RPort,spaces,1);
  806.             amii_curs(WIN_MESSAGE,colx,bottom);
  807.             did_comp=0;
  808.         }
  809.         }
  810.  
  811.         win = amii_create_nhwindow( NHW_MENU );
  812.         amii_start_menu( win );
  813.  
  814.         for( i = 0; extcmdlist[ i ].ef_txt != NULL; ++i )
  815.         {
  816.         sprintf( buf, "%-10s - %s ",
  817.              extcmdlist[ i ].ef_txt,
  818.              extcmdlist[ i ].ef_desc );
  819.         amii_add_menu( win, extcmdlist[i].ef_txt[0], 0, buf );
  820.         }
  821.  
  822.         amii_end_menu( win, i, "\33", NULL );
  823.         sel = amii_select_menu( win );
  824.         amii_destroy_nhwindow( win );
  825.  
  826.         if( sel == '\33' || !sel )
  827.         {
  828.         *obufp = '\33';
  829.         obufp[ 1 ] = 0;
  830.         return;
  831.         }
  832.         else
  833.         {
  834.         for( i = 0; extcmdlist[ i ].ef_txt != NULL; ++i )
  835.         {
  836.             if( sel == extcmdlist[i].ef_txt[0] )
  837.             break;
  838.         }
  839.  
  840.         /* copy in the text */
  841.         if( extcmdlist[ i ].ef_txt != NULL )
  842.         {
  843.             amii_clear_nhwindow( WIN_MESSAGE );
  844.             strcpy( obufp = bufp, extcmdlist[ i ].ef_txt );
  845.             (void) put_ext_cmd( obufp, colx, cw, bottom );
  846.             return;
  847.         }
  848.         else
  849.             DisplayBeep( NULL );
  850.         }
  851.     }
  852.     else if(c == '\033')
  853.     {
  854.         *obufp = c;
  855.         obufp[1] = 0;
  856.         return;
  857.     }
  858.     else if(c == '\b')
  859.     {
  860.         if(did_comp){
  861.         while(bufp!=obufp){
  862.             bufp--;
  863.             amii_curs(WIN_MESSAGE, --colx, bottom);
  864.             Text(w->RPort,spaces,1);
  865.             amii_curs(WIN_MESSAGE,colx,bottom);
  866.             did_comp=0;
  867.         }
  868.         }else
  869.         if(bufp != obufp)
  870.         {
  871.         bufp--;
  872.         amii_curs( WIN_MESSAGE, --colx, bottom);
  873.         Text( w->RPort, spaces, 1 );
  874.         amii_curs( WIN_MESSAGE, colx, bottom);
  875.         }
  876.         else
  877.         DisplayBeep( NULL );
  878.     }
  879.     else if( c == '\n' || c == '\r' )
  880.     {
  881.         *bufp = 0;
  882.         return;
  883.     }
  884.     else if(' ' <= c && c < '\177')
  885.     {
  886.         /* avoid isprint() - some people don't have it
  887.            ' ' is not always a printing char */
  888.         *bufp = c;
  889.         bufp[1] = 0;
  890.         oindex = 0;
  891.         com_index = -1;
  892.  
  893.         while(extcmdlist[oindex].ef_txt != NULL)
  894.         {
  895.         if(!strnicmp(obufp, extcmdlist[oindex].ef_txt, strlen(obufp)))
  896.         {
  897.             if(com_index == -1) /* No matches yet*/
  898.             com_index = oindex;
  899.             else /* More than 1 match */
  900.             com_index = -2;
  901.         }
  902.         oindex++;
  903.         }
  904.  
  905.         if(com_index >= 0 && *obufp )
  906.         {
  907.         Strcpy(obufp, extcmdlist[com_index].ef_txt);
  908.         /* finish printing our string */
  909.         colx = put_ext_cmd( obufp, colx, cw, bottom );
  910.         bufp = obufp; /* reset it */
  911.         if(strlen(obufp) < BUFSZ-1 && strlen(obufp) < COLNO)
  912.             bufp += strlen(obufp);
  913.         did_comp=1;
  914.         }
  915.         else
  916.         {
  917.         colx = put_ext_cmd( obufp, colx, cw, bottom );
  918.         if(bufp-obufp < BUFSZ-1 && bufp-obufp < COLNO)
  919.             bufp++;
  920.         }
  921.     }
  922.     else if(c == ('X'-64) || c == '\177')
  923.     {
  924.         colx = 0;
  925.         amii_clear_nhwindow( WIN_MESSAGE );
  926.         pline( "# " );
  927.         bufp = obufp;
  928.     } else
  929.         DisplayBeep( NULL );
  930.     }
  931.     *bufp = 0;
  932.     return;
  933. }
  934.  
  935. static int
  936. put_ext_cmd( obufp, colx, cw, bottom )
  937.     char *obufp;
  938.     int colx, bottom;
  939.     struct amii_WinDesc *cw;
  940. {
  941.     struct Window *w = cw->win;
  942.     char *t;
  943.  
  944.     t = malloc( strlen( obufp ) + 7 );
  945.     if( t != NULL )
  946.     {
  947.     if( scrollmsg )
  948.     {
  949.         sprintf( t, "xxx%s", obufp );
  950.         t[0] = 1;
  951.         t[1] = -1;
  952.         t[2] = ' ';
  953.         amii_curs( WIN_MESSAGE, 0, bottom);
  954.         SetAPen( w->RPort, C_WHITE );
  955.         Text(w->RPort, "># ", 3 );
  956.         SetAPen( w->RPort, C_RED );
  957.         Text(w->RPort, t+3, strlen( t ) - 3 );
  958.     }
  959.     else
  960.     {
  961.         sprintf( t, "# %s", obufp );
  962.         amii_curs( WIN_MESSAGE, 0, bottom);
  963.         SetAPen( w->RPort, C_WHITE );
  964.         Text(w->RPort, t, strlen( t ) );
  965.     }
  966.     if( scrollmsg )
  967.         SetAPen( w->RPort, C_WHITE );
  968.     if( cw->data[ cw->maxrow - 1 ] )
  969.         free( cw->data[ cw->maxrow - 1 ] );
  970.     cw->data[ cw->maxrow - 1 ] = t;
  971.     }
  972.     else
  973.     {
  974.     amii_curs( WIN_MESSAGE, 0, bottom);
  975.     SetAPen( w->RPort, C_WHITE );
  976.     Text(w->RPort, "# ", 2 );
  977.     SetAPen( w->RPort, C_RED );
  978.     Text(w->RPort, obufp, strlen( obufp ) );
  979.     SetAPen( w->RPort, C_WHITE );
  980.     }
  981.     amii_curs( WIN_MESSAGE, colx = strlen( obufp ) + 3 + ( scrollmsg != 0 ), bottom);
  982.     return( colx );
  983. }
  984. #endif /* COM_COMPL */
  985.  
  986. #ifdef WINDOW_YN
  987. SHORT Ask_BorderVectors1[] = { 0,0, 29,0, 29,11, 0,11, 0,0 };
  988. struct Border Ask_Border1 = { -1,-1, 3,0,JAM1, 5, Ask_BorderVectors1, NULL };
  989. struct IntuiText Ask_IText1 = { 3,0,JAM2, 2,1, NULL, "(?)", NULL };
  990.  
  991. struct Gadget Ask_Gadget1 = {
  992.     NULL, 9,4, 28,10, NULL, RELVERIFY, BOOLGADGET, (APTR)&Ask_Border1,
  993.     NULL, &Ask_IText1, NULL, NULL, NULL, NULL
  994. };
  995.  
  996. #define Ask_GadgetList1 Ask_Gadget1
  997.  
  998. struct IntuiText Ask_IText2 = { 1,0,JAM2, 44,5, NULL, NULL, NULL };
  999.  
  1000. #define Ask_IntuiTextList1 Ask_IText2
  1001.  
  1002. struct NewWindow Ask_Window = {
  1003.     75,85, 524,18, 0,1, GADGETUP+VANILLAKEY, ACTIVATE+NOCAREREFRESH,
  1004.     &Ask_Gadget1, NULL, NULL, NULL, NULL, 5,5, -1,-1, CUSTOMSCREEN
  1005. };
  1006. #endif
  1007.  
  1008. /* Ask a question and get a response */
  1009.  
  1010. #ifdef OLDCODE
  1011.  
  1012. char amii_yn_function( prompt, resp, def )
  1013.     const char *prompt,*resp;
  1014.     char def;
  1015. {
  1016.     char ch;
  1017.     char buf[ 80 ];
  1018.  
  1019.     if( def && def!='q')
  1020.     {
  1021.     sprintf( buf, "%s [%c] ", prompt, def );
  1022.     amii_addtopl( buf );
  1023.     } else {
  1024.     amii_addtopl( prompt );
  1025.     }
  1026.  
  1027.     cursor_on( WIN_MESSAGE );
  1028.     do {
  1029.     ch = WindowGetchar();
  1030.     if( ch == '\33' )
  1031.         break;
  1032.     else if( def && ( ch == '\n' || ch == '\r' ) )
  1033.     {
  1034.         ch = def;
  1035.         break;
  1036.     }
  1037.     else if( isdigit(ch) && index(resp, '#')){
  1038.         
  1039.     }
  1040.     } while( resp && *resp && index( resp, ch ) == 0 );
  1041.  
  1042.     cursor_off( WIN_MESSAGE );
  1043.     if( ch == '\33' )
  1044.     {
  1045.     if(index(resp, 'q'))
  1046.         ch = 'q';
  1047.     else if(index(resp, 'n'))
  1048.         ch = 'n';
  1049.     else ch = def;
  1050.     }
  1051.     /* Try this to make topl behave more appropriately? */
  1052.     clear_nhwindow( WIN_MESSAGE );
  1053.     return( ch );
  1054. }
  1055. #else
  1056. char amii_yn_function(query,resp, def)
  1057. const char *query,*resp;
  1058. char def;
  1059. /*
  1060.  *   Generic yes/no function. 'def' is the default (returned by space or
  1061.  *   return; 'esc' returns 'q', or 'n', or the default, depending on
  1062.  *   what's in the string. The 'query' string is printed before the user
  1063.  *   is asked about the string.
  1064.  *   If resp is NULL, any single character is accepted and returned.
  1065.  */
  1066. {
  1067.     register char q;
  1068.     char rtmp[40];
  1069.     boolean digit_ok, allow_num;
  1070.     char prompt[QBUFSZ];
  1071.     register struct amii_WinDesc *cw;
  1072.  
  1073.     if( cw = amii_wins[ WIN_MESSAGE ] )
  1074.         cw->disprows = 0;
  1075.     if(resp) {
  1076.         allow_num = (index(resp, '#') != 0);
  1077.         if(def)
  1078.         Sprintf(prompt, "%s [%s] (%c) ", query, resp, def);
  1079.         else
  1080.         Sprintf(prompt, "%s [%s] ", query, resp);
  1081.         amii_addtopl(prompt);
  1082.     } else {
  1083.         amii_addtopl(query);
  1084.         cursor_on(WIN_MESSAGE);
  1085.         q = WindowGetchar();
  1086.         cursor_off(WIN_MESSAGE);
  1087. #if 1
  1088.         TOPL_NOSPACE;
  1089.         *rtmp = q;
  1090.         rtmp[ 1 ] = 0;
  1091.         amii_putstr(WIN_MESSAGE,-1,rtmp);
  1092.         TOPL_SPACE;
  1093. #endif
  1094.         goto clean_up;
  1095.     }
  1096.  
  1097.     do {    /* loop until we get valid input */
  1098.         cursor_on(WIN_MESSAGE);
  1099.         q = lowc(WindowGetchar());
  1100.         cursor_off(WIN_MESSAGE);
  1101. #if 0
  1102. /* fix for PL2 */
  1103.         if (q == '\020') { /* ctrl-P */
  1104.         if(!doprev) (void) tty_doprev_message(); /* need two initially */
  1105.         (void) tty_doprev_message();
  1106.         q = (char)0;
  1107.         doprev = 1;
  1108.         continue;
  1109.         } else if(doprev) {
  1110.         tty_clear_nhwindow(WIN_MESSAGE);
  1111.         cw->maxcol = cw->maxrow;
  1112.         doprev = 0;
  1113.         amii_addtopl(prompt);
  1114.         continue;
  1115.         }
  1116. #endif
  1117.         digit_ok = allow_num && isdigit(q);
  1118.         if (q == '\033') {
  1119.         if (index(resp, 'q'))
  1120.             q = 'q';
  1121.         else if (index(resp, 'n'))
  1122.             q = 'n';
  1123.         else
  1124.             q = def;
  1125.         break;
  1126.         } else if (index(quitchars, q)) {
  1127.         q = def;
  1128.         break;
  1129.         }
  1130.         if (!index(resp, q) && !digit_ok) {
  1131.         amii_bell();
  1132.         q = (char)0;
  1133.         } else if (q == '#' || digit_ok) {
  1134.         char z, digit_string[2];
  1135.         int n_len = 0;
  1136.         long value = 0;
  1137.         TOPL_NOSPACE;
  1138.         amii_addtopl("#"),  n_len++;
  1139.         TOPL_SPACE;
  1140.         digit_string[1] = '\0';
  1141.         if (q != '#') {
  1142.             digit_string[0] = q;
  1143.             TOPL_NOSPACE;
  1144.             amii_addtopl(digit_string),  n_len++;
  1145.             TOPL_SPACE;
  1146.             value = q - '0';
  1147.             q = '#';
  1148.         }
  1149.         do {    /* loop until we get a non-digit */
  1150.             cursor_on(WIN_MESSAGE);
  1151.             z = lowc(WindowGetchar());
  1152.             cursor_off(WIN_MESSAGE);
  1153.             if (isdigit(z)) {
  1154.             value = (10 * value) + (z - '0');
  1155.             if (value < 0) break;    /* overflow: try again */
  1156.             digit_string[0] = z;
  1157.             TOPL_NOSPACE;
  1158.             amii_addtopl(digit_string),  n_len++;
  1159.             TOPL_SPACE;
  1160.             } else if (z == 'y' || index(quitchars, z)) {
  1161.             if (z == '\033')  value = -1;    /* abort */
  1162.             z = '\n';    /* break */
  1163.             } else if ( z == '\b') {
  1164.             if (n_len <= 1) { value = -1;  break; }
  1165.             else { value /= 10;  removetopl(1),  n_len--; }
  1166.             } else {
  1167.             value = -1;    /* abort */
  1168.             amii_bell();
  1169.             break;
  1170.             }
  1171.         } while (z != '\n');
  1172.         if (value > 0) yn_number = value;
  1173.         else if (value == 0) q = 'n';        /* 0 => "no" */
  1174.         else {    /* remove number from top line, then try again */
  1175.             removetopl(n_len),  n_len = 0;
  1176.             q = '\0';
  1177.         }
  1178.         }
  1179.     } while(!q);
  1180.  
  1181.     if (q != '#') {
  1182.         Sprintf(rtmp, "%c", q);
  1183. #if 0
  1184.         amii_addtopl(rtmp);
  1185. #else
  1186.         TOPL_NOSPACE;
  1187.         amii_putstr(WIN_MESSAGE,-1,rtmp);
  1188.         TOPL_SPACE;
  1189. #endif
  1190.     }
  1191.     clean_up:
  1192.     cursor_off(WIN_MESSAGE);
  1193.     clear_nhwindow(WIN_MESSAGE);
  1194.     return q;
  1195. }
  1196.  
  1197. #endif
  1198.  
  1199.  
  1200. void
  1201. amii_display_file(fn, complain)
  1202. const char *fn;
  1203. boolean complain;
  1204. {
  1205.     register struct amii_WinDesc *cw;
  1206.     register int win;
  1207.     register FILE *fp;
  1208.     register char *t;
  1209.     register char buf[ 200 ];
  1210.  
  1211.     if( fn == NULL )
  1212.     panic("NULL file name in display_file()");
  1213.  
  1214.     if( ( fp = fopenp( fn, "r" ) ) == NULL )
  1215.     {
  1216.     if (complain) {
  1217.         sprintf( buf, "Can't display %s: %s", fn,
  1218. #ifdef  __SASC_60
  1219.             __sys_errlist[ errno ]
  1220. #else
  1221.             sys_errlist[ errno ]
  1222. #endif
  1223.             );
  1224.         amii_addtopl( buf );
  1225.     }
  1226.     return;
  1227.     }
  1228.     win = amii_create_nhwindow( NHW_TEXT );
  1229.  
  1230.     /* Set window title to file name */
  1231.     if( cw = amii_wins[ win ] )
  1232.     cw->morestr = fn;
  1233.  
  1234.     while( fgets( buf, sizeof( buf ), fp ) != NULL )
  1235.     {
  1236.     if( t = index( buf, '\n' ) )
  1237.         *t = 0;
  1238.     amii_putstr( win, 0, buf );
  1239.     }
  1240.     fclose( fp );
  1241.  
  1242.     /* If there were lines in the file, display those lines */
  1243.  
  1244.     if( amii_wins[ win ]->cury > 0 )
  1245.     amii_display_nhwindow( win, TRUE );
  1246.  
  1247.     amii_wins[win]->morestr = NULL;        /* don't free title string */
  1248.     amii_destroy_nhwindow( win );
  1249. }
  1250.  
  1251. /* Put a 3-D motif border around the gadget.  String gadgets or those
  1252.  * which do not have highlighting are rendered down.  Boolean gadgets
  1253.  * are rendered in the up position by default.
  1254.  */
  1255.  
  1256. void
  1257. SetBorder( gd )
  1258.     register struct Gadget *gd;
  1259. {
  1260.     register struct Border *bp;
  1261.     register short *sp;
  1262.     register int i, inc = -1, dec = -1;
  1263.     int borders = 6;
  1264.  
  1265.     /* Allocate two border structures one for up image and one for down
  1266.      * image, plus vector arrays for the border lines.
  1267.      */
  1268.  
  1269.     if( gd->GadgetType == STRGADGET )
  1270.     borders = 12;
  1271.  
  1272.     if( ( bp = (struct Border *)alloc( ( ( sizeof( struct Border ) * 2 ) +
  1273.             ( sizeof( short ) * borders ) ) * 2 ) ) == NULL )
  1274.     {
  1275.     return;
  1276.     }
  1277.  
  1278.     /* For a string gadget, we expand the border beyond the area where
  1279.      * the text will be entered.
  1280.      */
  1281.  
  1282.     /* Remove any special rendering flags to avoid confusing intuition
  1283.      */
  1284.  
  1285.     gd->Flags &= ~(GADGHIGHBITS|GADGIMAGE);
  1286.  
  1287.     sp = (short *)(bp + 4);
  1288.     if( gd->GadgetType == STRGADGET || ( gd->GadgetType == BOOLGADGET &&
  1289.                 ( gd->Flags & GADGHIGHBITS ) == GADGHNONE ) )
  1290.     {
  1291.     sp[0] = -1;
  1292.     sp[1] = gd->Height - 1;
  1293.     sp[2] = -1;
  1294.     sp[3] = -1;
  1295.     sp[4] = gd->Width - 1;
  1296.     sp[5] = -1;
  1297.  
  1298.     sp[6] = gd->Width + 1;
  1299.     sp[7] = -2;
  1300.     sp[8] = gd->Width + 1;
  1301.     sp[9] = gd->Height + 1;
  1302.     sp[10] = -2;
  1303.     sp[11] = gd->Height + 1;
  1304.  
  1305.     sp[12] = -2;
  1306.     sp[13] = gd->Height;
  1307.     sp[14] = -2;
  1308.     sp[15] = -2;
  1309.     sp[16] = gd->Width;
  1310.     sp[17] = -2;
  1311.     sp[18] = gd->Width;
  1312.     sp[19] = gd->Height;
  1313.     sp[20] = -2;
  1314.     sp[21] = gd->Height;
  1315.  
  1316.     for( i = 0; i < 3; ++i )
  1317.     {
  1318.         bp[ i ].LeftEdge = bp[ i ].TopEdge = -1;
  1319.         bp[ i ].FrontPen = ( i == 0 || i == 1 ) ? C_BLUE : C_WHITE;
  1320.  
  1321.         /* Have to use JAM2 so that the old colors disappear. */
  1322.         bp[ i ].BackPen = C_BLACK;
  1323.         bp[ i ].DrawMode = JAM2;
  1324.         bp[ i ].Count = ( i == 0 || i == 1 ) ? 3 : 5;
  1325.         bp[ i ].XY = &sp[ i*6 ];
  1326.         bp[ i ].NextBorder = ( i == 2 ) ? NULL : &bp[ i + 1 ];
  1327.     }
  1328.  
  1329.     /* bp[0] and bp[1] two pieces for the up image */
  1330.     gd->GadgetRender = (APTR) bp;
  1331.  
  1332.     /* No image change for select */
  1333.     gd->SelectRender = (APTR) bp;
  1334.  
  1335.     gd->LeftEdge++;
  1336.     gd->TopEdge++;
  1337.     gd->Flags |= GADGHCOMP;
  1338.     }
  1339.     else
  1340.     {
  1341.     /* Create the border vector values for up and left side, and
  1342.      * also the lower and right side.
  1343.      */
  1344.  
  1345.     sp[0] = dec;
  1346.     sp[1] = gd->Height + inc;
  1347.     sp[2] = dec;
  1348.     sp[3] = dec;
  1349.     sp[4] = gd->Width + inc;
  1350.     sp[5] = dec;
  1351.  
  1352.     sp[6] = gd->Width + inc;
  1353.     sp[7] = dec;
  1354.     sp[8] = gd->Width + inc;
  1355.     sp[9] = gd->Height + inc;
  1356.     sp[10] = dec;
  1357.     sp[11] = gd->Height + inc;
  1358.  
  1359.     /* We are creating 4 sets of borders, the two sides of the
  1360.      * rectangle share the border vectors with the opposite image,
  1361.      * but specify different colors.
  1362.      */
  1363.  
  1364.     for( i = 0; i < 4; ++i )
  1365.     {
  1366.         bp[ i ].TopEdge = bp[ i ].LeftEdge = 0;
  1367.  
  1368.         /* A GADGHNONE is always down */
  1369.  
  1370.         if( gd->GadgetType == BOOLGADGET &&
  1371.                 ( gd->Flags & GADGHIGHBITS ) != GADGHNONE )
  1372.         {
  1373.         bp[ i ].FrontPen =
  1374.                 ( i == 1 || i == 2 ) ? C_BLUE : C_WHITE;
  1375.         }
  1376.         else
  1377.         {
  1378.         bp[ i ].FrontPen =
  1379.                 ( i == 1 || i == 3 ) ? C_WHITE : C_BLUE;
  1380.         }
  1381.  
  1382.         /* Have to use JAM2 so that the old colors disappear. */
  1383.         bp[ i ].BackPen = C_BLACK;
  1384.         bp[ i ].DrawMode = JAM2;
  1385.         bp[ i ].Count = 3;
  1386.         bp[ i ].XY = &sp[ 6 * ((i &1) != 0) ];
  1387.         bp[ i ].NextBorder =
  1388.                 ( i == 1 || i == 3 ) ? NULL : &bp[ i + 1 ];
  1389.     }
  1390.  
  1391.     /* bp[0] and bp[1] two pieces for the up image */
  1392.     gd->GadgetRender = (APTR) bp;
  1393.  
  1394.     /* bp[2] and bp[3] two pieces for the down image */
  1395.     gd->SelectRender = (APTR) (bp + 2);
  1396.     gd->Flags |= GADGHIMAGE;
  1397.     }
  1398. }
  1399.  
  1400. #ifndef    SHAREDLIB
  1401. #if 0
  1402. void *
  1403. malloc( register unsigned size )
  1404. {
  1405.     register long *p;
  1406.  
  1407.     size += 4;
  1408.     p = AllocMem( size, MEMF_PUBLIC );
  1409.     if( p ) *p++ = size;
  1410.     else panic( "No memory left" );
  1411.     return( p );
  1412. }
  1413.  
  1414. void
  1415. free( void *q )
  1416. {
  1417.     register long *p = q;
  1418.  
  1419.     if( !q )
  1420.     panic( "free of NULL pointer" );
  1421.     FreeMem( p-1, p[-1] );
  1422. }
  1423. #endif
  1424. #endif
  1425.